﻿// Gateway.Api 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// 
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// 
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;

namespace Aurora.AI.SqlSugar.Framework;
/// <summary>
/// sql sugar 映射扩展类
/// </summary>
public static class SqlSugarMappingExtension
{
    public static SqlSugarDbContext? GetDbContext(this IServiceProvider serviceProvider, Type type)
    {
        TableUsageAttribute? tableUsageAttribute = type.GetCustomAttribute<TableUsageAttribute>();
        if (tableUsageAttribute != null)
        {
            return serviceProvider.GetKeyedService<SqlSugarDbContext>(tableUsageAttribute.Name ?? "");
        }
        return serviceProvider.GetKeyedService<SqlSugarDbContext>("default");
    }


    /// <summary>
    /// 获取 映射的类
    /// </summary>
    /// <param name="assembly"></param>
    /// <returns></returns>
    public static Dictionary<Type, Type> GetMappingTypes(this Assembly assembly)
    {
        // 扫描mapping 
        Type genericType = typeof(IEntityMapping<>);
        Dictionary<Type, Type> mappingTypes = new Dictionary<Type, Type>();
        foreach (Type type in assembly.GetTypes())
        {
            if (!type.IsClass)
                continue;
            if (type.IsAbstract)
                continue;
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
            Type firstOrDefault = type.GetInterfaces()
                .FirstOrDefault(t => t.IsGenericType
                                     && t.GetGenericTypeDefinition() == genericType);
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
            if (firstOrDefault != null)
            {
                // 证明是这个接口
                mappingTypes.Add(type, firstOrDefault.GetGenericArguments()[0]);
            }
        }
        return mappingTypes;
    }

    /// <summary>
    /// 映射字段
    /// </summary>
    /// <param name="p"></param>
    /// <param name="mappingTypes"></param>
    public static void EntityServiceMapping(this EntityColumnInfo p, Dictionary<Type, Type> mappingTypes)
    {
        foreach (KeyValuePair<Type, Type> item in mappingTypes)
        {
            // 创建 entity column info 
            Type entityColumnableType = typeof(EntityColumnable<>);
            Type entityColumnTableGenericType = entityColumnableType.MakeGenericType(item.Value);

            PropertyInfo entityColumnInfoPropertyInfo =
                entityColumnTableGenericType.GetProperty("entityColumnInfo");
            PropertyInfo isTablePropertyInfo = entityColumnTableGenericType.GetProperty("IsTable");
            // 创建实例，假设我们使用整数42作为构造函数的参数
            object entityColumnableInstance =
                Activator.CreateInstance(entityColumnTableGenericType, null);
            // 
            if (entityColumnInfoPropertyInfo != null)
            {
                entityColumnInfoPropertyInfo.SetValue(entityColumnableInstance, p);
            }

            if (isTablePropertyInfo != null)
            {
                isTablePropertyInfo.SetValue(entityColumnableInstance, p.EntityName == item.Value.Name);
            }
            // 反射
            object instance = Activator.CreateInstance(item.Key)!;
            // 执行方法
            // 使用泛型接口
            instance.GetType()!.GetMethod("EntityServiceMapping")!.Invoke(
                instance, new object[] { entityColumnableInstance });
        }
    }
    /// <summary>
    /// 映射表名
    /// </summary>
    /// <param name="type"></param>
    /// <param name="entityInfo"></param>
    /// <param name="mappingTypes"></param>
    public static void EntityNameServiceMapping(this EntityInfo entityInfo, Type type, Dictionary<Type, Type> mappingTypes)
    {
        foreach (KeyValuePair<Type, Type> item in mappingTypes)
        {
            if (type != item.Value)
            {
                continue;
            }
            // 反射
            object instance = Activator.CreateInstance(item.Key)!;
            // 执行方法
            // 使用泛型接口
            instance.GetType()!.GetMethod("EntityNameServiceMapping")!.Invoke(
                instance, new object[] { entityInfo });
        }
    }

    /// <summary>
    /// 初始化表
    /// </summary>
    /// <param name="scope"></param>
    /// <param name="mappingTypes"></param>
    public static void InitTables(this SqlSugarScope scope, Dictionary<Type, Type> mappingTypes)
    {
        foreach (KeyValuePair<Type, Type> item in mappingTypes)
        {
            scope.CodeFirst.InitTables(item.Value);
        }
    }
}